/**
 * com.chaeron.GPS - An API for access to GPS devices.
 *
 *
 * Copyright (c) 2001, 2002 Chaeron Corporation,
 * All rights reserved.
 * 
 * Chaeron grants you a non-exclusive license to use, modify and re-distribute
 * this program under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version, provided that this copyright notice and 
 * license appear on all copies of the software.
 * 
 * Software is provided "AS IS," without a warranty of any kind. ALL EXPRESS OR
 * IMPLIED REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
 * HEREBY EXCLUDED. THE ENTIRE RISK ARISING OUT OF USING THE SOFTWARE IS ASSUMED
 * BY THE LICENSEE. See the GNU General Public License for more details.
 *
 * CHAERON AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE OR ANY THIRD PARTY AS A RESULT OF USING OR DISTRIBUTING SOFTWARE.
 * IN NO EVENT WILL CHAERON OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE,
 * PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL
 * OR PUNITIVE DAMAGES, HOWEVER CAUSED AN REGARDLESS OF THE THEORY OF LIABILITY,
 * ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF CHAERON HAS
 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 * @version     1.02
 * @author      Andrzej Jan Taramina, Chaeron Corporation
 *              andrzej@chaeron.com
 */

package com.chaeron.GPS.NMEA;

//***************************************************************************
//*
//*     Imports
//*
//***************************************************************************/

import com.chaeron.GPS.*;
import com.chaeron.GPS.event.*;
import com.chaeron.GPS.exception.*;


//***************************************************************************
//*
//*     GGASentence Class definition
//*
//***************************************************************************/

/**
 * The GGASentence class represents NMEA GGA - GPS Fix Data
 *
 */

public class GGASentence extends NMEASentence implements GPSPosition, GPSTime
{
	//***************************************************************************
	//*
	//*     Constant definitions
	//*
	//***************************************************************************/
	
	private final static int		GGA_NUM_FIELDS				= 14;
	
	
	//***************************************************************************
	//*
	//*     Attributes
	//*
	//***************************************************************************/
	
	private float		altitude					= 0.0f;
	private float		epe							= 0.0f;
	private float		eph							= 0.0f;
	private float		epv							= 0.0f;
	private short		fix							= 0;
	private float		utc							= 0.0f;
	private double		tow							= 0.0d;
	private double		latitude					= 0.0d;
	private double		longitude					= 0.0d;
	private float		east						= 0.0f;
	private float		north						= 0.0f;
	private float		up							= 0.0f;
	private float		mslHeight					= 0.0f;
	private short		leapSeconds					= 0;
	private int			wnDays						= 0;
	private int			satellites					= 0;
	private int			dgpsSec						= 0;
	private int			dgpsID						= 0;
	
	
	//***************************************************************************
	//*
	//*     Constructors
	//*
	//***************************************************************************/
	
	/**
	 * Create a GGASentence from the given packet data
	 *
	 * @param	tid			talker ID
	 * @param	sid			Sentence ID
	 * @param	sentenceStr	sentence string buffer
	 */
	
	GGASentence( int tid, int sid, String sentenceStr )
	{  
		super( tid, sid, sentenceStr );
		
		setFieldCount( GGA_NUM_FIELDS );
	}
	
	
	//***************************************************************************
	//*
	//*     Methods
	//*
	//***************************************************************************/
	
	/**
	 * Decode the data fields for a GGA sentence
	 *
	 * @return		This method will return a standard error code or GPS.ERROR_OK
	 * @throws GPSPacketException
	 * @throws GPSFunctionUnavailableException
	 */
	
	public void parseData() throws GPSPacketException, GPSFunctionUnavailableException
	{  
		int		i;
		
		if( getFieldCount() >= GGA_NUM_FIELDS ) {
			utc 		= getNMEAFloat( getField( 0 ) );					// UTC Time of fix
			latitude	= getNMEALatLong( getField( 1 ), getField( 2 ) );	// Latitude
			longitude	= getNMEALatLong( getField( 3 ), getField( 4 ) );	// Longitude
			fix			= getNMEAShort( getField( 5 ) );					// Fix type
			if( fix == 1 ) {												// Change it to suit
				fix = GPSPosition.GPSPOSITION_FIX_3D;
			} else if( fix == 2 ) {
				fix = GPSPosition.GPSPOSITION_FIX_3D_DIFFERENTIAL;
			}
			satellites	= getNMEAInt( getField( 6 ) );						// # Satellites
			eph			= getNMEAFloat( getField( 7 ) );					// EPH
			altitude	= getNMEAFloat( getField( 8 ) );					// Altitude
			mslHeight	= -getNMEAFloat( getField( 10 ) );					// MSL Height (make it positive)
			dgpsSec		= getNMEAInt( getField( 12 ) );						// seconds since DGPS update
			dgpsID		= getNMEAInt( getField( 13 ) );						// DGPS station ID
		} else {
			throw( new GPSPacketException( GPSPacketException.EXCEPTION_NUMFIELDS_INVALID ) );
		}
	}
	
	
	//***************************************************************************
	//*
	//*     Sentence Processing Methods
	//*
	//***************************************************************************/
	
	/**
	 * Process the sentence
	 *
	 * @param	gps			the GPS object that requested the GGA sentence to be processed
	 */
	
	void process( GPS gps )
	{
		gps.postGPSEvent( new GPSEvent( GPSEvent.GPS_EVENT_POSITION, this ) );
		gps.postGPSEvent( new GPSEvent( GPSEvent.GPS_EVENT_TIME, this ) );
	}
	
	
	/**
	 * Get events generated.
	 *
	 * @return		return a valid event type(s) that will be generated by this sentence subclass
	 */
	
	static int getEventsGenerated()
	{  
		return( GPSEvent.GPS_EVENT_POSITION | GPSEvent.GPS_EVENT_TIME | GPSEvent.GPS_EVENT_NMEA_SENTENCE );
	}
	
	
	/**
	 * Does the object contain valid data?
	 *
	 * @return		Does the object contain valid data?
	 */
	
	public boolean isDataValid()
	{  
		return( fix != GPSPosition.GPSPOSITION_FIX_UNUSEABLE && fix != GPSPosition.GPSPOSITION_FIX_INVALID );
	}
	
	
	//***************************************************************************
	//*
	//*    Accessor methods
	//*
	//***************************************************************************/
	
	/**
	 * Get the Altitude above WGS84 (meters)
	 *
	 * @return		Altitude
	 */
	
	public float getAltitude()
	{  
		return( altitude );
	}
	
	
	/**
	 * Get the Estimated Position Error (meters)
	 *
	 * @return		Estimated Position Error (meters)
	 */
	
	public float getEPE()
	{  
		return( epe );
	}
	
	
	/**
	 * Get the Estimated Position Error, horizontal only (meters)
	 *
	 * @return		Estimated Position Error, horizontal only (meters)
	 */
	
	public float getEPH()
	{  
		return( eph );
	}
	
	
	/**
	 * Get the Estimated Position Error, vertical only (meters)
	 *
	 * @return		Estimated Position Error, vertical only (meters)
	 */
	
	public float getEPV()
	{  
		return( epv );
	}
	
	
	/**
	 * Get the type of position fix
	 *
	 * @return		type of position fix
	 */
	
	public short getFixType()
	{  
		return( fix );
	}
	
	
	/**
	 * Get the time of week (seconds)
	 *
	 * @return		time of week (seconds)
	 */
	
	public double getTimeOfWeek()
	{  
		return( tow );
	}
	
	
	/**
	 * Get the UTC Time
	 *
	 * @return		UTC time
	 */
	
	public float getUTC()
	{  
		return( utc );
	}
	
	
	/**
	 * Get the Latitude (degrees)
	 *
	 * @return		Latitude (degrees)
	 */
	
	public double getLatitude()
	{  
		return( latitude );
	}
	
	
	/**
	 * Get the Longitude (degrees)
	 *
	 * @return		Longitude (degrees)
	 */
	
	public double getLongitude()
	{  
		return( longitude );
	}
	
	
	/**
	 * Get the velocity east
	 *
	 * @return		velocity east (meters/sec)
	 */
	
	public float getVelocityEast()
	{  
		return( east );
	}
	
	
	/**
	 * Get the velocity north
	 *
	 * @return		velocity north (meters/sec)
	 */
	
	public float getVelocityNorth()
	{  
		return( north );
	}
	
	
	/**
	 * Get the velocity up
	 *
	 * @return		velocity up (meters/sec)
	 */
	
	public float getVelocityUp()
	{  
		return( up );
	}
	
	
	/**
	 * Get the height of WGS 84 ellipsoid above MSL (meters)
	 *
	 * @return		height of WGS 84 ellipsoid above MSL (meters)
	 */
	
	public float getMSLHeight()
	{  
		return( mslHeight );
	}
	
	
	/**
	 * Get the difference between GPS and UTC times (seconds)
	 *
	 * @return		difference between GPS and UTC times (seconds)
	 */
	
	public short getLeapSeconds()
	{  
		return( leapSeconds );
	}
	
	
	/**
	 * Get the week number days
	 *
	 * @return		week number days
	 */
	
	public int getWeekNumberDays()
	{  
		return( wnDays );
	}
}
